package com.mohe.shanpao.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import com.mohe.shanpao.domain.user.SysFunction;
import com.mohe.shanpao.domain.user.SysRole;
import com.mohe.shanpao.domain.user.SysUser;
import com.mohe.shanpao.service.user.SysUserService;
import com.mohe.shanpao.utils.Constants;

public class ShiroRealm extends AuthorizingRealm
{
	@Autowired
    SysUserService sysUserService;
	
    @Override
    public boolean supports(AuthenticationToken authenticationtoken)
    {
        return authenticationtoken instanceof UsernamePasswordToken;
    }
    
    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalcollection)
    {
        //String username = (String)principalcollection.getPrimaryPrincipal(); 
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        Session session = SecurityUtils.getSubject().getSession();
        SysUser user = (SysUser)session.getAttribute(Constants.SYS_USER_INFO);
        
        if (!ObjectUtils.isEmpty(user) && !ObjectUtils.isEmpty(user.getSysRoles()))
        {
        	for (SysRole role : user.getSysRoles())
        	{
        		authorizationInfo.addRole(role.getName());//角色
        		
        		if (!ObjectUtils.isEmpty(role.getSysFunction()))
        		{
        			for (SysFunction sysFunction : role.getSysFunction())
        			{
        				authorizationInfo.addStringPermission(sysFunction.getPermission());//权限
        			}
        		}
        	}
        }
        
        return authorizationInfo;
    }
    
    /**
     * 鉴权
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationtoken)
    {
        //用户认证token
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationtoken;
        String username = (String)token.getPrincipal();
        
        SysUser user = sysUserService.selectUser(username);
        
        //用户不存在
        if (ObjectUtils.isEmpty(user))
        {
            throw new UnknownAccountException();//没找到帐号异常
        }
        
        if(Boolean.TRUE.equals(user.isLocked())) {
            throw new LockedAccountException(); //帐号锁定
        }
        
//        String salt = user.getSalt();
//        String password2 = CommonUtils.generatePassword(username, password, salt, Constants.DEAFULT_ALGORITHM_NAME);
//        if (!password2.equals(user.getPassword()))
//        {
//            throw new IncorrectCredentialsException();//密码错误异常
//        }
        
        //更新登录session
//        Subject currentUser = SecurityUtils.getSubject();
//        Session session = currentUser.getSession();
//        session.setAttribute(Constants.SYS_USER_INFO, user);
        
//        SimpleAuthenticationInfo sai = new SimpleAuthenticationInfo(username , password , getName());
//        sai.setCredentialsSalt(ByteSource.Util.bytes(salt));
        
        String salt = username.concat(user.getSalt());
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getName(), //用户名
                user.getPassword(), //密码
                ByteSource.Util.bytes(salt),//salt=username+salt
                getName()
        );
        
        return authenticationInfo;
    }
    
    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }
}
